const acorn = require('acorn');
const jsx = require('acorn-jsx');
const fs = require('fs');
const path = require('path');

// 配置支持JSX和最新语法
const parser = acorn.Parser.extend(jsx());

// 特性检测规则映射表
const FEATURE_DETECTORS = {
  // 1. let/const
  'let/const': node => 
    node.type === 'VariableDeclaration' && 
    ['let', 'const'].includes(node.kind),
  // 2. 解构赋值 (对象和数组)
  '解构赋值': node => 
    (node.type === 'VariableDeclarator' &&  node.id &&
     (node.id.type === 'ObjectPattern' || node.id.type === 'ArrayPattern')) ||
    (node.type === 'AssignmentPattern' &&  node.left &&
     (node.left.type === 'ObjectPattern' || node.left.type === 'ArrayPattern')),
  // 3. 参数处理
  '默认参数': node => 
    node.type === 'AssignmentPattern' && 
    (node.parent && node.parent.type === 'FunctionParameter'),
  '剩余参数': node => 
    node.type === 'RestElement' && 
    (node.parent && node.parent.type === 'FunctionParameter'),  
  // 4. 生成器函数
  '生成器': node =>
    (node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') && 
    node.generator === true,
  // 5. raw标签函数
  'raw标签函数': node =>
    node.type === 'TaggedTemplateExpression' && node.tag &&
    node.tag.type === 'MemberExpression' &&
    node.tag.object?.name === 'String' &&
    node.tag.property?.name === 'raw',
  // 6. 对象特性
  '对象简写': node => 
    node.type === 'Property' && 
    node.shorthand === true,
  '计算属性名': node =>
    node.type === 'Property' && 
    node.computed === true,
  // 7. 合并语法
  '合并语法': node =>
    node.type === 'SpreadElement' && node.parent &&
    (node.parent.type === 'ArrayExpression' || node.parent.type === 'ObjectExpression'),
  // 8. 类与继承
  '类定义': node =>
    node.type === 'ClassDeclaration' || 
    node.type === 'ClassExpression',
  '类继承': node =>
    (node.type === 'ClassDeclaration' || node.type === 'ClassExpression') &&
    node.superClass !== null,
  // 9. 模块系统
  '动态导入': node => node.type === 'ImportExpression',
  '模块导入': node => node.type === 'ImportDeclaration',
  '默认导出': node => node.type === 'ExportDefaultDeclaration',
  '命名导出': node => node.type === 'ExportNamedDeclaration',
  //10. eval与with
  'eval调用': node => node.type === 'CallExpression' && node.callee &&
    node.callee.type === 'Identifier' && node.callee.name === 'eval',
  'with语句': node => node.type === 'WithStatement'
};

// 新增日志文件路径
const ES6_LOG = path.join(__dirname, 'es6_features.log');

// 初始化日志文件
async function initLogFiles() {
  await fs.promises.writeFile(ES6_LOG, '');
}

// AST遍历检测器
function detectFeatures(ast) {
  const detected = new Set();
  function traverse(node) {
    // 避免空节点
    if (node == null) {
      return;
    }
    // 检查所有检测规则
    for (const [feature, detector] of Object.entries(FEATURE_DETECTORS)) {
      if (detector(node)) detected.add(feature);
    }
    // 递归遍历子节点
    for (const key in node) {
      const child = node[key];
      if (child && typeof child === 'object') {
        if (Array.isArray(child)) {
          child.forEach(traverse);
        } else if (child.type) {
          traverse(child);
        }
      }
    }
  }
  traverse(ast);
  return detected;
}

// 保存ES6特性为TXT文件
async function saveFeatures(url, features, outputDir) {
  const fileName = `${path.basename(url)}-features.txt`;
  const filePath = path.join(outputDir, fileName);
  const content = `Detected ES6+ features for ${path.basename(url)}:\n` +
    features.map(f => `► ${f}`).join('\n');
  await fs.promises.writeFile(filePath, content, 'utf8');
  console.log(`Features saved to ${filePath}`);
}

// 处理单个文件
async function processFile(FilePath, outputDir) {
  try {
    const code = fs.readFileSync(FilePath, 'utf-8');
    let ast;
    try {
      ast = parser.parse(code, { ecmaVersion: 'latest', sourceType: 'module' });
    } catch (parseError) {
      console.error(`Error parsing file ${FilePath}: ${parseError.message}`);
      return;
    }
    const features = detectFeatures(ast);
    if (features.size > 0) {
      // 输出检测到的特性
      console.log(`Detected ES6+ features in ${FilePath}:`);
      console.log(Array.from(features).sort().join(', '));
      await saveFeatures(FilePath, Array.from(features).sort(), outputDir);
      // 记录包含ES6特性的文件
      const featuresString = Array.from(features).sort().join(', ');
      await fs.promises.appendFile(ES6_LOG, `${FilePath} - Features: ${featuresString}\n`);
    } else {
      console.log(`No ES6+ features detected in ${FilePath}`);
    }
  } catch (error) {
    console.error(`Error processing file ${FilePath}: ${error.message}`);
  }
}

// 使用示例
(async () => {
  try {
    await initLogFiles();
    const FilePath = 'es6/tx.js';    // 替换为您的文件路径
    const outputDir = 'es6/output'; // 替换为您希望保存输出的目录
    await processFile(FilePath, outputDir);
  } catch (error) {
    console.error('Error initializing or processing file:', error);
  }
})();
